package org.monkey.socket.plugin.handler;

import io.netty.channel.ChannelHandler.Sharable;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.FullHttpRequest;
import io.netty.handler.codec.http.websocketx.CloseWebSocketFrame;
import io.netty.handler.codec.http.websocketx.PingWebSocketFrame;
import io.netty.handler.codec.http.websocketx.PongWebSocketFrame;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import io.netty.handler.codec.http.websocketx.WebSocketFrame;
import lombok.extern.slf4j.Slf4j;
import org.monkey.socket.plugin.service.IMsgChannelManage;
import org.monkey.socket.plugin.service.IMsgDealAction;

@Slf4j
@Sharable
public class NioWebSocketHandler extends SimpleChannelInboundHandler<WebSocketFrame> {



  private IMsgDealAction msgDealAction;

  private IMsgChannelManage msgChannelManage;

  public NioWebSocketHandler(IMsgDealAction msgDealAction,IMsgChannelManage msgChannelManage) {
    this.msgDealAction = msgDealAction;
    this.msgChannelManage = msgChannelManage;
  }

  @Override
  public void channelActive(ChannelHandlerContext ctx) throws Exception {
    log.info("client connected：{}", ctx.channel().id());
    super.channelActive(ctx);
  }

  @Override
  public void channelInactive(ChannelHandlerContext ctx) throws Exception {
    log.info("client disconnected：{}", ctx.channel().id());
    msgChannelManage.disConnected(ctx);
    super.channelInactive(ctx);
  }

  @Override
  public void channelReadComplete(ChannelHandlerContext ctx) {
    ctx.channel().flush();
  }

  @Override
  protected void channelRead0(ChannelHandlerContext ctx, WebSocketFrame frame) {
    if (frame instanceof PingWebSocketFrame) {
      pingWebSocketFrameHandler(ctx, (PingWebSocketFrame) frame);
    } else if (frame instanceof TextWebSocketFrame) {
      textWebSocketFrameHandler(ctx, (TextWebSocketFrame) frame);
    } else if (frame instanceof CloseWebSocketFrame) {
      closeWebSocketFrameHandler(ctx, (CloseWebSocketFrame) frame);
    }
  }

  @Override
  public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
    if (msg instanceof FullHttpRequest) {
      fullHttpRequestHandler(ctx, (FullHttpRequest) msg);
    }
    super.channelRead(ctx, msg);
  }

  /**
   * 处理连接请求，客户端WebSocket发送握手包时会执行这一次请求
   *
   * @param ctx
   * @param request
   */
  private void fullHttpRequestHandler(ChannelHandlerContext ctx, FullHttpRequest request) {
    msgChannelManage.onLogin(ctx,request);
  }

  /**
   * 客户端发送断开请求处理
   *
   * @param ctx
   * @param frame
   */
  private void closeWebSocketFrameHandler(ChannelHandlerContext ctx, CloseWebSocketFrame frame) {
    log.info("accept closed request：{}", ctx.channel().id());
    msgChannelManage.onClose(ctx,frame);
    ctx.close();
  }

  /**
   * 创建连接之后，客户端发送的消息都会在这里处理
   *
   * @param ctx
   * @param frame
   */
  private void textWebSocketFrameHandler(ChannelHandlerContext ctx, TextWebSocketFrame frame) {
    String text = frame.text();
    msgDealAction.dealMsg(ctx,text);
  }

  /**
   * 处理客户端心跳包
   *
   * @param ctx
   * @param frame
   */
  private void pingWebSocketFrameHandler(ChannelHandlerContext ctx, PingWebSocketFrame frame) {
    log.info("heart check:{}", frame.content().copy().toString());
    ctx.channel().writeAndFlush(new PongWebSocketFrame(frame.content().retain()));
  }


}